import Overlay from "ol/Overlay";
import { POSITIONINGS } from "@/utils/ol/overlay/Tooltip";
// 计算提示框在上下左右四个位置的Rect
function getRects(tooltip) {
  const positioning = tooltip.getPositioning();
  const offset = 10;
  const rect = tooltip.getElement().getBoundingClientRect();
  let cx,
    cy,
    w = rect.width,
    h = rect.height;

  switch (positioning) {
    case POSITIONINGS.TOP:
      cx = rect.x + rect.width / 2;
      cy = rect.y + rect.height + offset;
      break;
    case POSITIONINGS.RIGHT:
      cx = rect.x - offset;
      cy = rect.y + rect.height / 2;
      break;
    case POSITIONINGS.BOTTOM:
      cx = rect.x + rect.width / 2;
      cy = rect.y - offset;
      break;
    case POSITIONINGS.LEFT:
      cx = rect.x + rect.width + offset;
      cy = rect.y + rect.height / 2;
      break;
  }

  const result = {
    TOP: {
      x: cx - w / 2,
      y: cy - h - offset,
      w,
      h,
    },
    RIGHT: {
      x: cx + offset,
      y: cy - h / 2,
      w,
      h,
    },
    BOTTOM: {
      x: cx - w / 2,
      y: cy + offset,
      w,
      h,
    },
    LEFT: {
      x: cx - w - offset,
      y: cy - h / 2,
      w,
      h,
    },
  };

  return result;
}

/**
 *  @abstract 判断两个矩形是否重叠 (碰撞检测- 使用aabb算法)
 * @param {{x: number, y: number, w: number, h: number}} a 矩形a
 * @param {{x: number, y: number, w: number, h: number}} b 矩形b
 * @returns {boolean} 是否重叠
 */
export function isRectOverlay_aabb(a, b) {
  return !(
    a.x + a.w <= b.x ||
    b.x + b.w <= a.x ||
    a.y + a.h <= b.y ||
    b.y + b.h <= a.y
  );
}

/**
 * 计算两个矩形之间的重叠面积
 * @param {{x: number, y: number, w: number, h: number}} a 矩形a
 * @param {{x: number, y: number, w: number, h: number}} b 矩形b
 * @returns {number} 重叠面积
 */
function calculateOverlapArea(a, b) {
  const dx = Math.max(0, Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x));
  const dy = Math.max(0, Math.min(a.y + a.h, b.y + b.h) - Math.max(a.y, b.y));
  return dx * dy;
}

// overlay 布局优化
export function layoutOptimized(overlays) {
  const overlaysRects = []; // 所有overlay的矩形
  const chosenPositions = []; // 所有overlay的最终位置

  // 遍历所有overlay
  for (let i = 0; i < overlays.length; i++) {
    const overlay = overlays[i]; // 当前overlay
    const rects = getRects(overlay); // 当前overlay的矩形 (上下左右四个位置的矩形)
    let maxWeight = -Infinity; // 最大权重

    let bestPos = "TOP"; // 最佳位置

    // 遍历所有位置
    for (let posIdx = 0; posIdx < Object.keys(POSITIONINGS).length; posIdx++) {
      const posKey = Object.keys(POSITIONINGS)[posIdx];
      const rect = rects[posKey]; // 当前位置的矩形
      let overlayArea = 0; // 当前位置下的重叠面积

      // 遍历所有已布局的overlay的矩形,计算重叠面积
      for (let j = 0; j < overlaysRects.length; j++) {
        overlayArea += isRectOverlay_aabb(rect, overlaysRects[j])
          ? calculateOverlapArea(rect, overlaysRects[j])
          : 0;
      }

      // 根据重叠面积计算权重
      const posWeight = -overlayArea;

      // 更新最佳位置
      if (posWeight > maxWeight) {
        maxWeight = posWeight;
        bestPos = posKey;
      }

      if (posWeight === 0) break;
    }

    overlaysRects.push(rects[bestPos]);
    chosenPositions.push(bestPos);
  }

  overlays.forEach((overlay, idx) => {
    overlay.setPositioning(POSITIONINGS[chosenPositions[idx]]);
  });

}


export function layoutOptimized2(overlays) {
  const overlaysRects = []; // 所有overlay的矩形
  const chosenPositions = []; // 所有overlay的最终位置

  for (let i = 0; i < overlays.length; i++) {
    const overlay = overlays[i];
    const rects = getRects(overlay);
    overlaysRects.push(rects);
    chosenPositions.push("TOP");
  }

  // 遍历所有overlay
  for (let i = 0; i < overlays.length; i++) {
    const overlay = overlays[i];
    const rects = overlaysRects[i]; // 当前overlay的矩形 (上下左右四个位置的矩形)
    let maxWeight = -Infinity; // 最大权重
    let bestPos = "TOP"; // 最佳位置


    // 遍历所有位置
    for (let posIdx = 0; posIdx < Object.keys(POSITIONINGS).length; posIdx++) {
      const posKey = Object.keys(POSITIONINGS)[posIdx];
      const rect = rects[posKey]; // 当前位置的矩形
      let overlayArea = 0; // 当前位置下的重叠面积

      // 遍历所有已布局的overlay的矩形,计算重叠面积
      for (let j = 0; j < chosenPositions.length; j++) {
        if (i !== j) {
          const rect2 = overlaysRects[j][chosenPositions[j]];

          overlayArea += isRectOverlay_aabb(rect, rect2)
            ? calculateOverlapArea(rect, rect2)
            : 0;
        }
      }

      // 根据重叠面积计算权重
      const posWeight = -overlayArea;

      // 更新最佳位置
      if (posWeight > maxWeight) {
        maxWeight = posWeight;
        bestPos = posKey;
      }

      if (posWeight === 0) break;
    }

    chosenPositions[i] = bestPos;
  }

  overlays.forEach((overlay, idx) => {
    overlay.setPositioning(POSITIONINGS[chosenPositions[idx]]);
  });
}

/**
 * @abstract 碰撞检测
 * @param {Overlay} a overlay a
 * @param {Overlay} b overlay b
 * @returns {boolean} 是否碰撞
 */
export function collisionDetection(a, b) {
  const rectsA = a.getElement().getBoundingClientRect();
  const rectsB = b.getElement().getBoundingClientRect();

  return isRectOverlay_aabb(rectsA, rectsB);
}
